package com.warm.base.jdk.reflect;

import java.lang.reflect.*;

/**
 * @Description 反射
 * @Author iyb-liangchuang
 * @Date 2021/3/30 9:37
 */
public class Client {
    /**
     * 动态操作
     *   1. 运行是时分析类的能力
     *   2. 运行时查看对象
     * 程序运行期间, Java运行时系统始终为所有对象维护一个 <运行时的类型标识> Class
     */

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        /* 获取反射对象的三种方法 */

        ReflectObj obj = new ReflectObj();
        Class c1 = obj.getClass();

        Class c2 = Class.forName(c1.getName());

        // T 是任意类型的 Java 类型(或void关键字) T.class 代表匹配的类对象
        Class c3 = ReflectObj.class;
        /* 一个 Class 对象实际上表示的是一个类型, 这个类型未必一定是一种类 */
        Class c31 = int.class;

        /** 动态创建类的实例 */
        // 1. Class.newInstance() 创建无参实例对象
        Object ins = c3.newInstance();
        // 2. Constructor.newInstance() 创建有参实例对象
        String c3Name = "c3Name";
        Object ins1 = c3.getDeclaredConstructor(String.class).newInstance(c3Name);


        /* 反射分析类能力 -- Field Method Constructor */
        Class superclass = c3.getSuperclass();
        // getModifiers() 返回一个整型数值, 用不同的开关位描述 public static 等修饰符的使用状况
        String modifiers = Modifier.toString(c3.getModifiers());

        // Constructor
        Constructor[] cons = c3.getDeclaredConstructors();
        for (Constructor c : cons) {
            String name = c.getName();
            String modifier = Modifier.toString(c.getModifiers());
            Class[] paramTypes = c.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                String paramTypeName = paramTypes[i].getName();
            }
        }

        // Method -- 和上面类似
        Method[] methods = c3.getDeclaredMethods();
        for (Method m : methods){
            Class<?> returnType = m.getReturnType();
            Class<?>[] paramTypes = m.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++){
                paramTypes[i].getName();
            }
        }

        // Field
        Field[] fields = c3.getDeclaredFields();
        for (Field f : fields){
        }

        /* 访问私有域的值 */
        Field cName = c3.getDeclaredField("name");
        cName.setAccessible(true); // 设置可访问权限
        Object cNameVal = cName.get(ins1);
        cName.set(ins1, "name1");

        // 调用方法
        Method mSub = c3.getDeclaredMethod("sub", Integer.class);
        mSub.setAccessible(true);
        Object invoke = mSub.invoke(ins1, 10);
        System.out.println(invoke);
    }
}
